import logging
import uuid

from django.contrib.auth.models import User
from django.db import models
from django.utils.timezone import now

from base.models import Profile

logger = logging.getLogger(__name__)


class RefreshFreqeuncy(models.TextChoices):
    DAILY = 'DAILY', 'Daily'
    WEEKLY = 'WEEKLY', 'Weekly'
    MONTHLY = 'MONTHLY', 'Monthly'
    YEARLY = 'YEARLY', 'Yearly'
    ONCE = 'ONCE', 'Once'


class DataSourceEntryStatus(models.TextChoices):
    PROCESSING = 'PROCESSING', 'Processing'
    READY = 'READY', 'Ready'
    FAILED = 'FAILED', 'Failed'
    MARKED_FOR_DELETION = 'MARKED_FOR_DELETION', 'Marked for deletion'


class DataSourceVisibility(models.IntegerChoices):
    PRIVATE = 0, 'Private'
    ORGANIZATION = 1, 'Organization'


class DataSourceType(models.Model):
    """
    Data source allows us to support different ways of getting data into the system
    """
    name = models.CharField(
        max_length=100, help_text='Name of the data source type',
    )
    slug = models.CharField(
        max_length=50, default='',
        help_text='Slug of the data source type',
    )
    description = models.TextField(
        default='', blank=True, help_text='Description of the data source type',
    )

    def __str__(self):
        return self.name


class DataSource(models.Model):
    """
    Individual data source
    """
    uuid = models.UUIDField(
        default=uuid.uuid4, editable=False, help_text='UUID of the data source',
    )
    type = models.ForeignKey(
        DataSourceType, on_delete=models.DO_NOTHING, help_text='Type of the data source',
    )
    owner = models.ForeignKey(
        User, on_delete=models.DO_NOTHING, help_text='Owner of the data source',
    )
    name = models.CharField(
        max_length=100, help_text='Name of the data source',
    )
    size = models.IntegerField(
        default=0, help_text='Size of the data source in bytes',
    )
    visibility = models.PositiveSmallIntegerField(
        default=DataSourceVisibility.PRIVATE, choices=DataSourceVisibility.choices, help_text='Visibility of the data source',
    )
    created_at = models.DateTimeField(
        help_text='Time when the data source was created', default=now,
    )
    updated_at = models.DateTimeField(
        auto_now=True, help_text='Time when the data source was updated',
    )

    def __str__(self):
        return self.name + ' (' + self.type.name + ')' + ' - ' + str(self.owner)


class DataSourceEntry(models.Model):
    """
    Individual file for a data source
    """
    uuid = models.UUIDField(
        default=uuid.uuid4, editable=False, help_text='UUID of the data source file',
    )
    datasource = models.ForeignKey(
        DataSource, on_delete=models.DO_NOTHING, help_text='Data source',
    )
    config = models.JSONField(
        default=dict, help_text='Config for the data source entry',
    )
    name = models.CharField(
        max_length=2048, help_text='Name of the data source file', blank=True, default='',
    )
    size = models.IntegerField(
        default=0, help_text='Size of the entry in bytes',
    )
    status = models.CharField(
        default=DataSourceEntryStatus.PROCESSING, max_length=100,
        choices=DataSourceEntryStatus.choices, help_text='Status of the data source entry',
    )
    refresh_frequency = models.CharField(
        default=RefreshFreqeuncy.ONCE, max_length=100,
        choices=RefreshFreqeuncy.choices, help_text='Refresh frequency of the data source entry',
    )
    created_at = models.DateTimeField(
        help_text='Time when the data source file was created', default=now,
    )
    updated_at = models.DateTimeField(
        auto_now=True, help_text='Time when the data source file was updated',
    )

    def user_can_read(self, user) -> bool:
        if self.datasource.visibility == DataSourceVisibility.PRIVATE:
            return self.datasource.owner == user
        elif self.datasource.visibility == DataSourceVisibility.ORGANIZATION:
            return self.datasource.owner == user or Profile.objects.get(user=self.datasource.owner).organization == Profile.objects.get(user=user).organization
        return False
